package com.gzc.just.play.last.war.common.handler;

import com.gzc.just.play.last.war.common.distributed.ServiceInstance;
import com.gzc.just.play.last.war.common.net.NetUtils;
import com.gzc.just.play.last.war.common.registry.ServiceRegistry;
import com.gzc.just.play.last.war.common.scanner.MessageHandlerScanner;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.util.AttributeKey;

import java.nio.ByteOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import java.net.InetAddress;
import java.nio.ByteOrder;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 虚拟线程Netty服务器基类
 * 提供统一的Netty服务器实现，支持虚拟线程处理
 * 各个具体服务器（login-server, balance-server, central-server, scene-server）可以继承此类
 */
public abstract class VirtualThreadNettyServer {
    protected static final Logger logger = LoggerFactory.getLogger(VirtualThreadNettyServer.class);
    
    @Value("${server.boss-threads:1}")
    protected int bossThreads;
    
    @Value("${server.worker-threads:4}")
    protected int workerThreads;
    
    @Value("${server.idle-time:300}")
    protected int idleTime;
    
    @Value("${server.host:127.0.0.1}")
    protected String serverHost;
    
    @Value("${spring.cloud.nacos.discovery.enabled:true}")
    protected boolean nacosEnabled;
    
    @Value("${nacos.service.register.ip:127.0.0.1}")
    protected String nacosRegisterIp;
    
    @Autowired(required = false)
    protected MessageHandlerScanner messageHandlerScanner;
    
    @Autowired(required = false)
    protected ServiceRegistry serviceRegistry;
    
    protected EventLoopGroup bossGroup;
    protected EventLoopGroup workerGroup;
    protected Channel serverChannel;
    
    // 虚拟线程处理框架
    protected VirtualThreadServerFramework framework;
    
    // 会话管理
    protected final ConcurrentHashMap<Long, ChannelHandlerContext> activeConnections = new ConcurrentHashMap<>();
    protected final AtomicLong sessionIdGenerator = new AtomicLong(1000);
    
    // 服务实例信息
    protected ServiceInstance serviceInstance;
    
    // 防止重复启动标志
    private volatile boolean started = false;
    private final Object startLock = new Object();
    
    /**
     * 获取服务器类型，由子类实现
     */
    protected abstract VirtualThreadServerFramework.ServerType getServerType();
    
    /**
     * 获取 Netty 服务器端口，由子类实现
     * 子类应该读取各自的端口配置，例如：
     * - LoginServer: ${login.server.port:30001}
     * - CentralServer: ${central.server.port:60001}
     * - SceneServer: ${scene.server.port:50001}
     */
    protected abstract int getNettyPort();
    
    /**
     * 获取 Netty 服务器主机地址，由子类实现
     * 子类应该读取各自的主机配置，例如：
     * - LoginServer: ${login.server.host:127.0.0.1}
     * - CentralServer: ${central.server.host:127.0.0.1}
     * - BalanceServer: ${balance.server.host:127.0.0.1}
     * - SceneServer: ${scene.server.host:127.0.0.1}
     * - GateServer: ${gate.server.host:127.0.0.1}
     * 如果子类不重写，将使用基类中的默认值
     */
    protected String getNettyHost() {
        return serverHost;
    }
    
    /**
     * 初始化消息处理器，使用自动扫描和注册机制
     */
    protected void initializeHandlers() {
        // 如果MessageHandlerScanner可用，使用它自动注册处理器
        if (messageHandlerScanner != null) {
            messageHandlerScanner.registerHandlersForServerType(getServerType(), framework);
            logger.info("Automatically registered handlers for {} using annotation scanning", getServerType().getName());
        } else {
            logger.warn("MessageHandlerScanner not available, handlers must be registered manually by subclass");
        }
    }
    
    /**
     * 处理连接建立事件，由子类可重写
     */
    protected void onConnectionActive(ChannelHandlerContext ctx) {
        long sessionId = framework.startSession(ctx);
        ctx.channel().attr(ServerAttributes.SESSION_ID).set(sessionId);
        activeConnections.put(sessionId, ctx);
        
        logger.info("Connection established: {} with session ID: {} for server: {}", 
                   ctx.channel().remoteAddress(), sessionId, getServerType().getName());
    }
    
    /**
     * 处理连接关闭事件，由子类可重写
     */
    protected void onConnectionInactive(ChannelHandlerContext ctx) {
        Long sessionId = ctx.channel().attr(ServerAttributes.SESSION_ID).get();
        if (sessionId != null) {
            framework.stopSession(sessionId);
            activeConnections.remove(sessionId);
            
            logger.info("Connection closed: {} with session ID: {} for server: {}", 
                       ctx.channel().remoteAddress(), sessionId, getServerType().getName());
        }
    }
    
    /**
     * 处理消息读取事件，由子类可重写
     */
    protected void onMessageRead(ChannelHandlerContext ctx, ByteBuf msg) {
        // LengthFieldBasedFrameDecoder已经处理了长度字段，这里直接读取消息ID
        if (msg.readableBytes() < 4) {
            logger.warn("Received message with insufficient data for server: {}", getServerType().getName());
            return;
        }
        
        int messageId = msg.readIntLE();
        logger.debug("Received message from client: messageId={} for server: {}", messageId, getServerType().getName());
        
        // 读取消息体
        int bodyLen = msg.readableBytes();
        byte[] bytes = new byte[bodyLen];
        msg.readBytes(bytes);
        
        // 获取会话ID
        Long sessionId = ctx.channel().attr(ServerAttributes.SESSION_ID).get();
        if (sessionId == null) {
            logger.warn("No session ID found for connection: {} for server: {}", 
                       ctx.channel().remoteAddress(), getServerType().getName());
            return;
        }
        
        // 使用虚拟线程处理框架处理消息
        framework.submitMessage(sessionId, messageId, bytes);
    }
    
    /**
     * 处理异常事件，由子类可重写
     */
    protected void onExceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error("Connection exception for server: {}", getServerType().getName(), cause);
        ctx.close();
    }
    
    @PostConstruct
    public void start() {
        // 防止重复启动
        synchronized (startLock) {
            if (started) {
                logger.warn("{} is already started, skipping duplicate start", getServerType().getName());
                return;
            }
            started = true;
        }
        
        int port = getNettyPort();
        logger.info("Starting {} on port: {}", getServerType().getName(), port);
        
        try {
            // 创建虚拟线程处理框架
            logger.debug("Creating VirtualThreadServerFramework for {}", getServerType().getName());
            framework = new VirtualThreadServerFramework(getServerType());
            
            // 初始化消息处理器
            logger.debug("Initializing handlers for {}", getServerType().getName());
            initializeHandlers();
            
            logger.debug("Creating EventLoopGroups for {}", getServerType().getName());
            bossGroup = new NioEventLoopGroup(bossThreads);
            workerGroup = new NioEventLoopGroup(workerThreads);
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .option(ChannelOption.SO_REUSEADDR, true)
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childOption(ChannelOption.SO_RCVBUF, 65536)
                    .childOption(ChannelOption.SO_SNDBUF, 65536)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            
                            // 添加空闲状态处理器
                            // pipeline.addLast("idleStateHandler",
                            //     new IdleStateHandler(0, 0, idleTime));
                            
                            // 添加消息编码和解码器，支持与Unity客户端的兼容性
                            NetUtils.addNettyCodec(pipeline);
                            // 添加我们的消息处理器
                            pipeline.addLast("handler", new ServerChannelHandler());
                        }
                    });
            
            ChannelFuture future = bootstrap.bind(getNettyHost(), port).sync();
            serverChannel = future.channel();
            
            logger.info("{} started successfully on port: {}", getServerType().getName(), port);
            
            // TCP监听成功后，注册到Nacos
            registerToNacos(port);
            
        } catch (InterruptedException e) {
            logger.error("{} startup interrupted", getServerType().getName(), e);
            Thread.currentThread().interrupt();
            stop();
        } catch (Exception e) {
            logger.error("{} startup failed with exception: {}", getServerType().getName(), e.getMessage(), e);
            throw new RuntimeException("Failed to start " + getServerType().getName(), e);
        }
    }
    
    /**
     * 注册服务到Nacos
     */
    protected void registerToNacos(int port) {
        if (!nacosEnabled) {
            logger.info("Nacos discovery is disabled, skip service registration");
            return;
        }
        
        if (serviceRegistry == null) {
            logger.warn("ServiceRegistry not available, cannot register to Nacos");
            return;
        }
        
        try {
            // 使用配置的IP地址进行服务注册，默认为127.0.0.1
            String hostAddress = nacosRegisterIp;
            String serviceName = getServerType().name().toLowerCase().replace("_", "-");
            String instanceId = serviceName + "-" + hostAddress + "-" + port;
            
            serviceInstance = new ServiceInstance();
            serviceInstance.setInstanceId(instanceId);
            serviceInstance.setServiceName(serviceName);
            serviceInstance.setHost(hostAddress);
            serviceInstance.setPort(port);
            serviceInstance.setScheme("tcp");
            
            // 添加TCP就绪标记
            serviceInstance.addMetadata("tcpReady", "true");
            serviceInstance.addMetadata("serverType", getServerType().name());
            serviceInstance.addMetadata("startTime", String.valueOf(System.currentTimeMillis()));
            
            serviceRegistry.register(serviceInstance);
            logger.info("Registered {} to Nacos: instanceId={}, host={}, port={}", 
                       getServerType().getName(), instanceId, hostAddress, port);
        } catch (Exception e) {
            logger.error("Failed to register {} to Nacos", getServerType().getName(), e);
        }
    }
    
    @PreDestroy
    public void stop() {
        logger.info("Stopping {}...", getServerType().getName());
        
        // 从Nacos注销
        deregisterFromNacos();
        
        // 停止所有虚拟线程会话
        if (framework != null) {
            framework.stopAllSessions();
        }
        
        if (serverChannel != null) {
            serverChannel.close();
        }
        
        if (workerGroup != null) {
            workerGroup.shutdownGracefully();
        }
        
        if (bossGroup != null) {
            bossGroup.shutdownGracefully();
        }
        
        logger.info("{} stopped", getServerType().getName());
    }
    
    /**
     * 从Nacos注销服务
     */
    protected void deregisterFromNacos() {
        if (serviceInstance != null && serviceRegistry != null) {
            try {
                serviceRegistry.deregister(serviceInstance);
                logger.info("Deregistered {} from Nacos", getServerType().getName());
            } catch (Exception e) {
                logger.error("Failed to deregister {} from Nacos", getServerType().getName(), e);
            }
        }
    }
    
    /**
     * 获取当前活跃连接数
     */
    public int getActiveConnectionCount() {
        return activeConnections.size();
    }
    
    /**
     * 服务器通道处理器
     */
    private class ServerChannelHandler extends SimpleChannelInboundHandler<ByteBuf> {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
            onMessageRead(ctx, msg);
        }
        
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            onConnectionActive(ctx);
            super.channelActive(ctx);
        }
        
        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            onConnectionInactive(ctx);
            super.channelInactive(ctx);
        }
        
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            onExceptionCaught(ctx, cause);
        }
    }
    
    /**
     * 服务器连接属性
     */
    public static class ServerAttributes {
        public static final AttributeKey<Long> SESSION_ID = 
            AttributeKey.valueOf("sessionId");
        public static final AttributeKey<Long> USER_ID = 
            AttributeKey.valueOf("userId");
        public static final AttributeKey<String> USERNAME = 
            AttributeKey.valueOf("username");
        public static final AttributeKey<String> SERVER_TYPE = 
            AttributeKey.valueOf("serverType");
    }
}